/**
 * 
 */
package com.iol.stpso.isoa;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @author kawine
 *
 */
public class AnnotationHelper {

	private String clsName;
	private Class<?> clazz;
	private Class<? extends Annotation> annotationType;
	
	private static void checkNullClassName(String clsName){
		if(clsName==null||clsName.trim().length()==0) throw new NullPointerException("ClassName can't be Null");
	}

	public AnnotationHelper(){
		super();
	}
	
	public AnnotationHelper(String clsName) {
		this(clsName,null);
	}
	
	public AnnotationHelper(String clsName,Class<? extends Annotation> annotationType) {
		checkNullClassName(clsName);
		this.clsName = clsName.replace(".", "/").toUpperCase();
		try {
			this.clazz = Class.forName(clsName);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		this.annotationType = annotationType;
	}
	
	public AnnotationHelper(Class<?> clazz){
		this(clazz,null);
	}
	
	public AnnotationHelper(Class<?> clazz,Class<? extends Annotation> annotationType) {
		this.clazz = clazz;
		this.clsName = clazz.getSimpleName().toUpperCase();
		this.annotationType = annotationType;
	}
	
	private Annotation[] getTypeAnnotaitons(){
			return clazz.getAnnotations();
	}
	
	private Field[] getFields(){
		return clazz.getDeclaredFields();
	}

	private Method[] getMethods(){
		return clazz.getDeclaredMethods();
	}

	@SuppressWarnings("rawtypes")
	private Constructor[] getConstructors(){
		return clazz.getDeclaredConstructors();
	}

	public List<Annotation> listTypeAnnotation(){
		return (annotationType==null)? null:listTypeAnnotation(annotationType);
	}
	
	public List<Annotation> listTypeAnnotation(Class<? extends Annotation> annotationType){
		List<Annotation> annolist = new ArrayList<Annotation>();
		if(!clazz.isAnnotationPresent(annotationType)&&clsName!=null){
			System.out.println("@"+clazz.getSimpleName()+" is not annotation in class "+clsName);
		}else{
			for(Annotation annotation:getTypeAnnotaitons()){
					annolist.add(annotation);
			}
		}
		return annolist;
	}
	
	public Map<List<String>,List<Annotation>> mapFieldAnnotation(){
		return (annotationType==null)? null:mapFieldAnnotation(annotationType);
	}
	
	public Map<List<String>,List<Annotation>> mapFieldAnnotation(Class<? extends Annotation> clazz){
		Map<List<String>, List<Annotation>> map = new HashMap<List<String>, List<Annotation>>();
		List<Annotation> annolist = new ArrayList<Annotation>();
		List<String> fieldNamelist = new ArrayList<String>();
		if(getFields()!=null){
			for(Field field :getFields()){
				boolean is = field.isAnnotationPresent(clazz);
				if(is){
					fieldNamelist.add(field.getName());
					annolist.add(field.getAnnotation(clazz));
					map.put(fieldNamelist, annolist);
				}else{
					if(clsName!=null){
						System.out.println("@"+clazz.getSimpleName()+" is not annotation in class "+clsName+"-->"+field.getName());
					}
				}
			}
		}
		System.out.println(map);
		return map;
	}
	
	public List<Annotation> listFieldAnnotation(){
		return (annotationType==null)? null:listFieldAnnotation(annotationType);
	}

	public List<Annotation> listFieldAnnotation(Class<? extends Annotation> clazz){
		List<Annotation> values =new ArrayList<Annotation>();
		for(Entry<List<String>, List<Annotation>> entry:mapFieldAnnotation(clazz).entrySet()){
			values = entry.getValue();
		}
		return values;
	}
	
	public List<String> listFieldName(){
		return (annotationType==null)? null:listFieldName(annotationType);
	}

	public List<String> listFieldName(Class<? extends Annotation> clazz){
		List<String> keys =new ArrayList<String>();
		for(Entry<List<String>, List<Annotation>> entry:mapFieldAnnotation(clazz).entrySet()){
			keys = entry.getKey();
		}
		return keys;
	}

}
